home *** CD-ROM | disk | FTP | other *** search
- /* $Id$ */
-
- // SpewView is written by Pedja Bogdanovich
- // Permission is granted to freely use and distribute this software
- // provided this notice is left attached and no monetary gain is made.
-
- #import "SpewView.h"
- #import "Thinker.h"
-
- #define TEXTTIMEDEFAULT "Spew TextTime"
- #define SLEEPTIMEDEFAULT "Spew SleepTime"
-
- #define MINWIDTHRAT .2
- #define MAXWIDTHRAT .75
- #define MINCHARS 12
- #define MAXFONTRAT .075
- #define MINFONTRAT .025
- #define MINFONTSIZE 12
-
- #define exp2(x) pow(2,x)
- #define rnd() ((random()&0xffffff)/(float)0xffffff)
-
- static const char *fontlist[]={
- "Courier", "Courier-Oblique", "Courier-Bold", "Courier-BoldOblique",
- "Helvetica", "Helvetica-Oblique", "Helvetica-Bold", "Helvetica-BoldOblique",
- "Times-Roman", "Times-Italic", "Times-Bold", "Times-BoldItalic"
- // Add more fonts here...
- };
-
- static int pointsize[]={
- 14,18,24,32,36,48,56,64
- // Add more font-sizes here...
- };
-
- static NXColor pickColor()
- {
- int i;
- float r, g, b;
- switch([Window defaultDepthLimit]) {
- case NX_TwoBitGrayDepth:
- return NXConvertGrayToColor(1.-(random()%2)/3.);
- case NX_EightBitGrayDepth:
- return NXConvertGrayToColor(1.-(random()%128)/256.);
- case NX_TwelveBitRGBDepth:
- case NX_TwentyFourBitRGBDepth:
- default:
- i=random()%4096;
- r=fmod(i,16)/16;
- g=fmod(i-r,256)/256;
- b=(i-fmod(i,256))/4096;
- r=.2+r*.8; g=.2+g*.8; b=.2+b*.8; /* Not too dark. */
- return NXConvertRGBToColor(r,g,b);
- }
- }
-
- // fontsizes can be made font specific...
- static float pickFontSize(float fmin, float fmax)
- {
- int i, j=sizeof(pointsize)/sizeof(int);
- int imin=j-1, imax=0;
- for(i=0;i<j;i++) if(pointsize[i]>=fmin) { imin=i; break; }
- for(i=0;i<j;i++) if(pointsize[i]<=fmax) imax=i;
- if(imin>=imax) i=imin;
- else i=imin+random()%(imax-imin+1);
- return pointsize[i];
- }
-
- static Font *pickFont(float sz)
- {
- return [Font newFont:fontlist[random()%(sizeof(fontlist)/sizeof(char*))]
- size:sz /* matrix:NX_IDENTITYMATRIX*/];
- }
-
- @implementation SpewView
- + initialize
- {
- static NXDefaultsVector spewDefaults={
- {TEXTTIMEDEFAULT,"12"},
- {SLEEPTIMEDEFAULT,"2"},
- {NULL}};
- NXRegisterDefaults([NXApp appName],spewDefaults);
- return [super initialize];
- }
-
- - initFrame:(const NXRect *)fr
- {
- NXSize sz={1e6,1e6};
-
- [super initFrame:fr];
- textOnScreen=NO;
-
- textView=[[Text alloc] initFrame:NULL];
- // [textView setRetainedWhileDrawing:NO];
- [textView setVertResizable:YES];
- [[textView setHorizResizable:NO] setHorizResizable:NO];
- [[textView setSelectable:YES] setEditable:NO];
- [textView setMonoFont:YES];
- [textView setBackgroundGray:NX_BLACK];
- [textView setMaxSize:&sz];
-
- defaultTextTime=atoi(NXGetDefaultValue([NXApp appName],TEXTTIMEDEFAULT));
- defaultSleepTime=atoi(NXGetDefaultValue([NXApp appName],SLEEPTIMEDEFAULT));
- srandom(time(0));
- return self;
- }
-
- // spewAgain method will load new spew text into textView.
- // textView's text content, font, color, and frame are set.
- - spewAgain
- {
- char buf[200];
- char tmpfile[100];
- FILE *f;
- NXRect r;
- static const int alignment[]={NX_LEFTALIGNED,NX_RIGHTALIGNED,NX_CENTERED};
-
- sprintf(tmpfile,"/tmp/.#tmp_spew%08x",getpid());
- sprintf(buf,"sh -c 'cd %s; spew >%s'",
- [(BSThinker()) moduleDirectory:"Spew"],
- tmpfile);
- system(buf);
-
- if(f=fopen(tmpfile,"r")) {
- struct stat statbuf;
- char *spewtext;
- float w, h, x, y;
-
- fstat(fileno(f),&statbuf);
- spewtext=alloca(statbuf.st_size+1);
- fread(spewtext,1,statbuf.st_size,f); spewtext[statbuf.st_size]=0;
- fclose(f);
-
- // Random selections below don't work very well for small windows...
-
- // set color
- [textView setTextColor:pickColor()];
-
- // set font
- h=pickFontSize(MAX(MINFONTSIZE,NX_HEIGHT(&bounds)*MINFONTRAT), /* min */
- NX_HEIGHT(&bounds)*MAXFONTRAT); /* max font size */
- [textView setFont:pickFont(h)];
-
- // set width
- w=MAX(NX_WIDTH(&bounds)*MINWIDTHRAT,MINCHARS*[[textView font] pointSize]);
- x=NX_WIDTH(&bounds)*MAXWIDTHRAT;
- if(w<x) w+=(x-w)*rnd();
- [textView sizeTo:w :50];
-
- // set content
- [textView setSel:0 :[textView textLength]];
- [textView replaceSel:spewtext];
-
- // set alignment
- [textView setAlignment:alignment[random()%(sizeof(alignment)/sizeof(int))]];
-
- // set position; height is calculated by the text object
- [textView getFrame:&r];
- w=NX_WIDTH(&r); h=NX_HEIGHT(&r);
- x=NX_X(&bounds)+(NX_WIDTH(&bounds)-w)*rnd();
- y=NX_Y(&bounds)+(NX_HEIGHT(&bounds)-h)*rnd();
- [textView moveTo:x :y];
- }
- unlink(tmpfile);
- return self;
- }
-
- - drawSelf:(NXRect *)rects :(int)rectCount
- {
- if(rects==NULL || rectCount==0) return self;
- PSsetgray(NX_BLACK); NXRectFill(rects);
- return self;
- }
-
- - inspector:sender
- {
- char buf[MAXPATHLEN];
-
- if(!sharedInspectorPanel) {
- sprintf(buf,"%s/Spew.nib",[sender moduleDirectory:"Spew"]);
- [NXApp loadNibFile:buf owner:self withNames:NO];
-
- // load default values into inspector
- [textTimeField setIntValue:defaultTextTime];
- [textTimeField sendAction:[textTimeField action] to:[textTimeField target]];
- [sleepTimeField setIntValue:defaultSleepTime];
- [sleepTimeField sendAction:[sleepTimeField action] to:[sleepTimeField target]];
- }
- return sharedInspectorPanel;
- }
-
- // This method is stolen from BackView
- - (BOOL)timePassed:(BStimeval)delay
- {
- BStimeval now, msec;
- BOOL result;
-
- now=currentTimeInMs();
- if(SVthen==0) SVthen=now; /* added by shou-h@nexus.or.jp */
- msec=now-SVthen;
-
- /* so as not to suck too many cycles, if I'm waiting for some
- time more than a tenth of a second in the future, I sleep
- a while. This interval is short enough that the app shouldn't
- seem unresponsive to user actions.
-
- ok, so you'd never pull this trick if the user had to type.
- A better solution would be to coordinate the timed entry better,
- but I get slightly better performance from spinning in my
- timed entry (a bad idea for most apps...) */
-
- if((msec+120)<delay) {
- usleep(110000);
- return NO;
- }
-
- result=(msec>delay);
- if(result) SVthen=now;
-
- return result;
- }
-
-
- - oneStep
- {
- int t; char buf[12];
-
- if(sharedInspectorPanel) {
- t=[textTimeField intValue];
- if(t!=defaultTextTime) { /* update default texttime if needed */
- sprintf(buf,"%d",t); defaultTextTime=t;
- NXWriteDefault([NXApp appName],TEXTTIMEDEFAULT,buf);
- }
- t=[sleepTimeField intValue];
- if(t!=defaultSleepTime) { /* update default sleeptime if needed */
- sprintf(buf,"%d",t); defaultSleepTime=t;
- NXWriteDefault([NXApp appName],SLEEPTIMEDEFAULT,buf);
- }
- }
-
- if(textOnScreen) {
- if(![self timePassed:defaultTextTime*1000]) return self;
- [textView removeFromSuperview];
- } else {
- if(![self timePassed:defaultSleepTime*1000]) return self;
- [self spewAgain];
- [self addSubview:textView];
- [window makeFirstResponder:textView];
- }
- textOnScreen=!textOnScreen;
- [self display];
- return self;
- }
- @end
-
- /* EOF */